
import { toRaw, getCurrentInstance, reactive } from 'vue'

import type {
  TStateKey,
  TAnyObject,
  IState
} from '../types/type'
 
/**
 * 给对象加上辅助功能：$state、$toRaw
 * @param obj 初始值， 对象 
 * @param id 标识，记录日志用。[id=Symbol('_object')] - 对象的唯一标识符，默认为Symbol('_object')。
 */
export default class BaseObject<T extends TAnyObject> implements IState<T> {
  #id: TStateKey
  /**
   * 创建一个基础的对象，实现辅助工具的功能
   * @param obj 初始值，可以是对象，也可以是函数
   * @param id 标识，记录日志用
   */
  constructor (
    obj: T,
    id: TStateKey = Symbol('_object'),
  ) {
    this.#id = id
    // 设置具体的属性，浅层拷贝
    Object.assign(this, obj)
  }

  /**
   * 整体赋值。
   * 定义一个名为 $state 的 setter 方法，用于设置当前状态对象的值。
   */
  set $state(value: T) {
    // 要不要判断 value 的属性是否完整？
    Object.assign(this, value)
  }
 
  /**
   * 设置部分属性
   */
  $patch<T2 extends T>(value: T2) {
    Object.assign(this, value)
  }
 
  /**
   * 取原型，去掉内部方法
  */
  $toRaw<T extends TAnyObject>(): T {
    const obj = {} as TAnyObject
    const tmp: TAnyObject = toRaw(this)
    Object.keys(tmp).forEach((key: TStateKey) => {
      if (typeof key === 'symbol' || ((key as string).substring(0,1) !== '#')) {
        obj[key] = (tmp[key].$toRaw) ? tmp[key].$toRaw() : toRaw(tmp[key])
      }
    })
    return obj as T
  }
  
  // 各种标识
  /**
   * 获取标识，string | symbol
   */
  get $id(): TStateKey {
    return toRaw(this).#id
  }
   
}